#include "StdAfx.h"
#include "glObject.h"
#include <conio.h>

glObject::glObject(void)
{
	camera=CCamera::GetInstance();
	light=glLighting::GetInstance();
}

glObject::~glObject(void)
{
}

void glObject::Init()
{
	vboId=new GLuint[2];
	//model->LoadModel();

	glGenBuffers(2, vboId);
	glBindBuffer(GL_ARRAY_BUFFER, vboId[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex)*model->m_iNumVertices, model->m_aVertices, GL_STATIC_DRAW);
	glBindBuffer(GL_ARRAY_BUFFER, 0);

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId[1]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*model->m_iNumIndices, model->m_aIndices, GL_STATIC_DRAW);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

	maProjection=camera->GetProjectionMatrix();
	//if(textureCubeCount){
	//	camera->ComputeViewMatrix();
	//	maView=camera->GetViewMatrix();
	//	maView=camera->GetViewMatrixSky();
	//}else {
	camera->ComputeViewMatrix();
	maView=camera->GetViewMatrix();
	//}
	Matrix rx,ry,rz,scl,pos;
	if(rotation.x)
		rx.SetRotationX(rotation.x);
	else 
		rx.SetIdentity();
	if(rotation.y)
		ry.SetRotationY(rotation.y);
	else 
		ry.SetIdentity();
	if(rotation.z)
		rz.SetRotationZ(rotation.z);
	else 
		rz.SetIdentity();
	scl.SetScale(scale);
	pos.SetTranslation(position);
	
	maModel=ry*rx*rz*scl*pos;
	
	MvpMatrix = maModel*maView * maProjection;

	if(textureCubeCount)
	{
		for(int i=0;i<textureCubeCount;i++)
		{
			texture[i]->LoadEnvironment();
		}
	}else {
		for(int i=0;i<textureCount;i++)
		{
			texture[i]->LoadTexture();
		}
	}
	myShaders.Init();
}

void glObject::Draw()
{	
	if(myShaders.depth_Test)
		glEnable(GL_DEPTH_TEST);
	if(myShaders.culling)
		glEnable(GL_CULL_FACE);
	if(myShaders.alpha)
	{
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	}
	glUseProgram(myShaders.program);

	glBindBuffer(GL_ARRAY_BUFFER, vboId[0]);

	if(myShaders.positionAttribute != -1)
	{
		glEnableVertexAttribArray(myShaders.positionAttribute);
		glVertexAttribPointer(myShaders.positionAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
	}

	if(myShaders.a_Nomal != -1)
	{
		glEnableVertexAttribArray(myShaders.a_Nomal);
		glVertexAttribPointer(myShaders.a_Nomal, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),(Vector3*)0+1);
	}

	if(myShaders.a_bitangentL != -1)
	{
		glEnableVertexAttribArray(myShaders.a_bitangentL);
		glVertexAttribPointer(myShaders.a_bitangentL, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),(Vector3*)0+2);
	}

	if(myShaders.a_tangentL != -1)
	{
		glEnableVertexAttribArray(myShaders.a_tangentL);
		glVertexAttribPointer(myShaders.a_tangentL, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),(Vector3*)0+3);
	}

	if(myShaders.cameraAttribute != -1)
	{
		glUniform3f(myShaders.cameraAttribute,camera->m_v3CamPos.x,camera->m_v3CamPos.y,camera->m_v3CamPos.z);
	}

	if(myShaders.texcoordAttribute != -1)
	{
		glEnableVertexAttribArray(myShaders.texcoordAttribute);
		glVertexAttribPointer(myShaders.texcoordAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (Vector3*)0+4);
	}
	int i=0;
	if(myShaders.textureAttribute != -1)
	{
		if(!textureCubeCount)
		{
			glActiveTexture (GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_2D,texture[i]->id_Texture);
		}
		else 
		{
			glActiveTexture ( GL_TEXTURE0 );
			glBindTexture(GL_TEXTURE_CUBE_MAP,texture[i]->id_TextureSky);
		}
		glUniform1i(myShaders.textureAttribute, 0); 
	} else {
		if(myShaders.Heigh_Map != -1){
			glActiveTexture ( GL_TEXTURE0 );
			glBindTexture(GL_TEXTURE_2D,texture[i]->id_Texture);
			glUniform1i(myShaders.Heigh_Map, i);
		}
		if(myShaders.Blend_Map != -1){
			i++;
			glActiveTexture ( GL_TEXTURE0+i );
			glBindTexture(GL_TEXTURE_2D,texture[i]->id_Texture);			
			glUniform1i(myShaders.Blend_Map, i); 
		}
		if(myShaders.Dirt_Map != -1){
			i++;
			glActiveTexture (  GL_TEXTURE0+i );
			glBindTexture(GL_TEXTURE_2D,texture[i]->id_Texture);						
			glUniform1i(myShaders.Dirt_Map, i);
		}
		if(myShaders.Grass_Map != -1){
			i++;
			glActiveTexture (  GL_TEXTURE0+i );
			glBindTexture(GL_TEXTURE_2D,texture[i]->id_Texture);			
			glUniform1i(myShaders.Grass_Map, i);
		}
		if(myShaders.Rock_Map != -1){
			i++;
			glActiveTexture (  GL_TEXTURE0+i );
			glBindTexture(GL_TEXTURE_2D,texture[i]->id_Texture);
			glUniform1i(myShaders.Rock_Map, i);
		}
		
		if(myShaders.u_texture0 != -1){
			glActiveTexture (  GL_TEXTURE0+i );
			glBindTexture(GL_TEXTURE_2D,texture[i]->id_Texture);
			glUniform1i(myShaders.u_texture0, i);
			++i;
		}
		
		if(myShaders.u_texture1 != -1){
			glActiveTexture ( GL_TEXTURE0+i );
			glBindTexture(GL_TEXTURE_2D,texture[i]->id_Texture);
			glUniform1i(myShaders.u_texture1, i);
			i++;
		}
		
		if(myShaders.u_texture2 != -1){
			glActiveTexture ( GL_TEXTURE0+i );
			glBindTexture(GL_TEXTURE_2D,texture[i]->id_Texture);
			glUniform1i(myShaders.u_texture2, i);
			i++;
		}
		
		if(myShaders.offset != -1){
			extern float uv_offset;
			glUniform1f(myShaders.offset,uv_offset);
		}

		//lighting
	}

	if(myShaders.spotLight != -1)
	{
		glUniform3f(myShaders.spotLight,light->Light.spotDirection.x,light->Light.spotDirection.y,light->Light.spotDirection.z);
	}

	if(myShaders.LightDiffuseColor != -1)
	{
		glUniform4f(myShaders.LightDiffuseColor,light->Light.diffuse.x,light->Light.diffuse.y,light->Light.diffuse.z,light->Light.diffuse.w);
	}
	
	if(myShaders.LightSpecularColor != -1)
	{
		glUniform4f(myShaders.LightSpecularColor,light->Light.specular.x,light->Light.specular.y,light->Light.specular.z,light->Light.specular.w);
	}

	if(myShaders.AmbientComponent != -1)
	{
		glUniform4f(myShaders.AmbientComponent,light->Light.ambient.x,light->Light.ambient.y,light->Light.ambient.z,light->Light.ambient.w);
	}
	//end lighting u_lightPosition

	if(myShaders.mvpMatrixUniform != -1)
	{
		glUniformMatrix4fv(myShaders.mvpMatrixUniform,1,GL_FALSE,(GLfloat*)MvpMatrix.m);
	}

	if(myShaders.ma_ViewAttribute != -1)
	{
		glUniformMatrix4fv(myShaders.ma_ViewAttribute,1,GL_FALSE,(GLfloat*)maModel.m);
	}
	
	if(myShaders.u_modelTranpose != -1)
	{
		glUniformMatrix4fv(myShaders.u_modelTranpose,1,GL_FALSE,(GLfloat*)maModel.m);
	}

	if(myShaders.u_modelMatrix != -1)
	{
		glUniformMatrix4fv(myShaders.u_modelMatrix,1,GL_FALSE,(GLfloat*)maModel.m);
	}

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId[1]);
	glDrawElements(GL_TRIANGLES,model->m_iNumIndices,GL_UNSIGNED_INT,0);
	glBindBuffer(GL_ARRAY_BUFFER, 0);

	glDisable(GL_DEPTH_TEST);
	glDisable(GL_CULL_FACE);
	glDisable(GL_BLEND);
}

void glObject::Update(){
	//if(!textureCubeCount){
		maView=camera->ComputeViewMatrix();
		MvpMatrix = maModel*maView * maProjection;
	//}
	//else{
	//	camera->ComputeViewMatrix();
	//	maView=camera->GetViewMatrixSky();
	//	MvpMatrix = maModel*maView * maProjection;
	//}
}

void glObject::CleanUp(){
	for(int i=0;i<textureCount;i++)
	{
		if(textureCubeCount){
			for(int j=0;j<textureCubeCount;j++)
				delete texture[j]->path_CubeTexture;
		}
		texture[i]->CleanUp();
	}
	delete []vboId;
	delete []texture;
	delete model;
}